package ioc.demo1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.ContextLoader;

/**
 * Created by dycong on 2017/4/21.
 */
public class Test {
    public static void main(String[] args)
    {
        System.out.println("====运行A中的main函数，准备载入xml配置文件====");
        ApplicationContext appContext=new ClassPathXmlApplicationContext("ioc/applicationContext1.xml");
        System.out.println("====xml配置文件载入完毕，准备获得bean D====");
        D d=(D)appContext.getBean("beand");
        System.out.println("====已经获取bean D，准备运行D中的方法methodOfD====");
        d.methodOfD();
        ContextLoader.getCurrentWebApplicationContext();
    }
    /**
     *  1. 按照xml配置文件中类的定义顺序加载类并创建类的实例。
     　　2. 假设当前要加载X类，则先运行X的static块。如果此时X的父类Y还没有加载，则先查找配置文件来加载Y，运行Y的static块，这样一直递归下去。当X的所有先驱类的static块运行完
        毕后，再类似递归地实例化X的先驱类(运行先驱类的普通初始化块和构造函数)，完成所有先驱类的实例化后才运行X的普通初始化块和构造函数。
     　　3. 执行完X的构造函数之后，开始根据xml配置文件给X的成员变量赋初值。如果X的引用型成员变量所属的类还未加载，则先查找配置文件来加载(初始化、实例化)该成员变量所属的类，
        加载完毕后将其注入给X的成员变量，完成成员变量的初始化。
     */
    /*
    1、调用Bean的默认构造方法，或者在指定的构造方法，生成bean实例（暂称为instance1）；

    3、如果Bean的配置文件中注入了Bean属性值，则在instance1基础上进行属性注入形成instance2，这种注入是覆盖性的。

    2、如果Bean实现了InitializingBean接口，则调用afterPropertiesSet()方法，来改变或操作instance2，得到instance3；

    4、如果Bean的配置文件中指定了init-ethod="init"属性，则会调用指定的初始化方法，则在instance3的基础上调用初始化方法init()，将对象最终初始化为instance4；初始化的名字任意。
     */

    /*
    @DependsOn用于强制初始化其他Bean。可以修饰Bean类或方法，使用该Annotation时可以指定一个字符串数组作为参数，每个数组元素对应于一个强制初始化的Bean “depends-on”属性可以指定多个Bean，若指定多个Bean可以用“;”、“,”、空格分割。
    @DependsOn({"steelAxe"})  初始化的晚销毁的早
    @Lazy用于指定该Bean是否取消预初始化。主要用于修饰spring Bean类，用于指定该Bean的预初始化行为，使用该Annotation时可以指定一个boolean型的value属性，该属性决定是否要预初始化该Bean。
     @Lazy(true)
     */

    /*自动装配:
    自动装配的好处是减少构造器注入和setter注入配置，减少配置文件的长度。自动装配通过配置<bean>标签的“autowire”属性来改变自动装配方式。接下来让我们挨着看下配置的含义。

       一、default：表示使用默认的自动装配，默认的自动装配需要在<beans>标签中使用default-autowire属性指定，其支持“no”、“byName ”、“byType”、“constructor”四种自动装配，如果需要覆盖默认自动装配，请继续往下看；

       二、no：意思是不支持自动装配，必须明确指定依赖。

       三、byName：通过设置Bean定义属性autowire="byName"，意思是根据名字进行自动装配，只能用于setter注入。比如我们有方法“setHelloApi”，则“byName”方式Spring容器将查找名字为helloApi的Bean并注入，如果找不到指定的Bean，将什么也不注入。

     不要配置<property>了，如果一个bean有很多setter注入，通过“byName”方式是不是能减少很多<property>配置。此处注意了，在根据名字注入时，将把当前Bean自己排除在外：比如“hello”Bean类定义了“setHello”方法，则hello是不能注入到“setHello”的。

           四、“byType”：通过设置Bean定义属性autowire="byType"，意思是指根据类型注入，用于setter注入，比如如果指定自动装配方式为“byType”，而“setHelloApi”方法需要注入HelloApi类型数据，则Spring容器将查找HelloApi类型数据，如果找到一个则注入该Bean，
           如果找不到将什么也不注入，如果找到多个Bean将优先注入<bean>标签“primary”属性为true的Bean，否则抛出异常来表明有个多个Bean发现但不知道使用哪个。

     */
}
